home *** CD-ROM | disk | FTP | other *** search
-
-
- Internet Engineering Task Force Robert E. Gilligan
- INTERNET-DRAFT Sun Microsystems, Inc.
- March 26, 1993
-
-
-
- SIP Program Interfaces for BSD Systems
-
-
- Abstract
-
- In order to implement the Simple Internet Protocol (SIP) [1] in an
- operating system based on 4.x BSD, changes must be made to some of the
- application program interfaces (APIs). TCP/IP applications written for
- BSD-based operating systems have in the past enjoyed a high degree of
- portability because most of the systems derived from BSD provide the
- same API, known informally as "the socket interface". We would like the
- same portability to be possible with SIP applications. This memo
- presents a set of changes to the BSD socket API to support SIP. The
- changes include a new data structure to carry 64-bit SIP addresses, a
- new name to address translation library function, new address conversion
- functions, and some new setsockopt() options. The changes are designed
- to be minimal and to provide source and binary compatibility for
- existing applications.
-
-
- Status of this Memo
-
- Internet Drafts are working documents of the Internet Engineering Task
- Force (IETF), its Areas, and its Working Groups. Note that other groups
- may also distribute working documents as Internet Drafts.
-
- Internet Drafts are draft documents valid for a maximum of six months.
- This Internet Draft expires on September 26, 1993. Internet Drafts may
- be updated, replaced, or obsoleted by other documents at any time. It is
- not appropriate to use Internet Drafts as reference material or to cite
- them other than as a "working draft" or "work in progress."
-
- Please check the I-D abstract listing contained in each Internet Draft
- directory to learn the current status of this or any other Internet
- Draft.
-
- Distribution of this memo is unlimited.
-
-
- 1. Introduction.
-
- The most visible feature of SIP is its extension of the length of an IP
- address from 32 bits to 64 bits. The APIs that the BSD system provides
- make the size of an IP address quite visible to an application.
- Virtually all TCP/IP applications for BSD-based systems have knowledge
- of the size of an IP address. Generally speaking, those parts of the
- API that make addresses visible need to be changed. This paper presents
- a first attempt to define the API changes needed to support SIP in BSD
-
-
-
- systems. These APIs are expected to evolve as we gain more
- implementation experience.
-
-
- 2. Design considerations
-
- There are two important considerations in designing changes to these
- well-worn APIs. First, the modified API should provide both source and
- binary compatibility for programs written to the existing API. That is,
- exiting program binaries should continue to operate when run on or
- re-compiled and run a system supporting the new APIs. The API changes
- for SIP should not cause existing program binaries to break, nor should
- they cause programs written to the existing APIs to fail to compile or
- break when re-compiled.
-
- Second, the changes should be as minimal as possible and should make it
- as easy as possible to change an existing application to be SIP
- knowledgeable.
-
-
- 2.1 What needs to be changed
-
- Since their address arguments are all opaque pointers, none of the
- socket system calls need to changed directly.
-
- The in_addr structure is 4-bytes long and can not be changed without
- breaking applications. The sockaddr_in structure, which is passed into
- and returned by the socket functions, contains 8 bytes of unused space
- which can be used to hold a SIP address without incompatibility.
-
- The gethostbyaddr() function includes an address type argument, so this
- function does not need to be changed. However, the gethostbyname()
- function does not include a type argument, and most applications that
- use it assume that the address array that it returns consists of 4-byte
- IP addresses. Thus a new function similar to gethostbyname(), but
- knowledgeable of SIP addresses, must be defined.
-
- Finally, a new interface is needed in order to set the SIP flow ID. The
- most straightforward way to do this is to define new setsockopt()
- options at the IPPROTO_IP level.
-
-
- 2.2 Implementation experience
-
- The Sun IPAE/SIP prototype exposed some of the issues in designing a
- compatible interface. The initial prototype passed SIP addresses
- between the kernel and applications using the sockaddr_in structure with
- the sin_family field set to AF_INET. The 8-byte SIP address occupied
- the 4 bytes of the "sin_addr" field plus the first 4 bytes of the
- "sin_zero" field. The kernel distinguished between 8-byte SIP addresses
- and 4-byte IPv4 addresses passed in by checking the sin_zero field. If
- sin_zero was zero, the kernel would assume that the sin_addr field held
- a 4-byte IPv4 address. If sin_zero was non-zero, it would assume that
- an 8-byte SIP address was being passed in.
-
-
-
-
- While this technique works for most existing applications, we discovered
- that some applications do not set the sin_zero field of the sockaddr_in
- structure to zero. Thus we concluded that it would be unworkable in the
- general case and that some specific indication was needed to distinguish
- a 8-byte SIP address from a 4-byte IPv4 address in a sockaddr_in
- structure.
-
- Another useful lesson learned from the initial Sun implementation was
- that the form of addresses (IPv4 or SIP) passed in and out of the socket
- functions did not always need to constrain the form of packets (IPv4,
- IPAE or SIP) transmitted or received. For example, a pre-existing TCP
- server application that knows nothing of SIP could accept a connection
- that was transmitting and receiving TCP segments encapsulated within SIP
- packets. Because SIP and IPv4 addresses are mappable, the accept()
- system call can return to the application the client's address as a
- 4-byte IPv4 address.
-
- What does matter, however, is that pre-existing applications never be
- given address structures that they don't understand. We found that the
- most convenient way for the kernel to decide what form of address to
- pass back to applications was to look at the form of addresses passed
- in. That is, if an application passes in IPv4 form addresses, then it
- should always be given IPv4 form addresses. If the application passes
- in SIP form addresses, the kernel can return SIP form addresses to the
- application.
-
-
- 3. Interface specification
-
-
- 3.1. New address family
-
- We define a address family macro in <sys/socket.h>:
-
- #define AF_SIP 24 /* Simple Internet Protocol */
-
- The AF_SIP definition is used only to distinguish between the original
- AF_INET form of the sockaddr_in structure, and a new form that we have
- defined. Thus there is no corresponding PF_SIP definition.
-
-
- 3.2 Sockaddr_in structure
-
- The sockaddr_in structure is used in the socket system calls to pass
- addresses between the application and the kernel. Keeping the
- sockaddr_in structure the same size is necessary to provide binary
- compatibility for existing IPv4 applications. We can avoid changing the
- size of the sockaddr_in structure by appropriating the currently unused
- sin_zero field to hold the 64 bit SIP address.
-
- We can add a structure element for the SIP address without changing the
- original structure definition by just adding two new macros. The
- resulting definition in the <netinet/in.h> header file is:
-
-
-
- struct sockaddr_in {
- short sin_family;
- u_short sin_port;
- in_addr sin_addr;
- char sin_zero[8];
- }
- #define sip_addr sin_zero
- #define sip_zero sin_addr
-
- The value of the sin_family field determines whether the sockaddr_in
- structure is holding a 32 bit IPv4 address or a 64 bit SIP address. The
- sin_family field may have one of two values: AF_INET or AF_SIP. If
- sin_family is AF_SIP, then the sip_addr field contains a 8-byte SIP
- address and the sip_zero field must be set to zero. If the sin_family
- field is AF_INET, then the sockaddr_in keeps its original semantics: The
- sin_addr field contains a 4-byte IPv4 address and the sin_zero field
- must be set to zero.
-
- We refer to the the two variants as the "AF_INET form" or the "AF_SIP
- form" of the sockaddr_in structure.
-
- The two structure layouts can be understood better when viewed
- graphically. This is the AF_INET form of the sockaddr_in structure:
-
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | AF_INET | port number |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | IPv4 address |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | |
- + all zero bits +
- | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
- And this is the layout of the AF_SIP form of the sockaddr_in structure:
-
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | AF_SIP | port number |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | all zero bits |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
- | |
- + SIP address +
- | |
- +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
-
- We considered an alternative form that overlays the high-order four
- bytes of the SIP address with sin_addr. The form presented has a few
- advantages:
-
- - The SIP address is aligned on a 64-bit boundary within the
- structure.
-
- - The kernel can do some consistency checking on AF_SIP addresses
-
-
-
- passed in. Because the sip_zero field, which overlays the
- sin_addr field, must always zero, the kernel can detect cases
- where the application incorrectly treats an AF_SIP form
- sockaddr_in as an AF_INET form.
-
- - The structure declaration is simpler than the alternative.
-
- 3.3 The socket functions
-
- Even though we define a new address family for SIP, there is no change
- to the way that applications get sockets. There is not a new "type" of
- socket for SIP. SIP applications continue use AF_INET in the "domain"
- argument (the first argument) of the socket() call. For example, to get
- a TCP socket, a SIP application would call:
-
- s = socket (AF_INET, SOCK_STREAM, 0);
-
- and to get a UDP socket, a SIP application would call:
-
- s = socket (AF_INET, SOCK_DGRAM, 0);
-
- Once the application has a socket, it may use either the AF_SIP or the
- AF_INET form of the sockaddr_in structure in the system calls that pass
- addresses in to the kernel.
-
- The form of sockaddr_in structure returned to the application by the
- socket functions is determined by the form of addresses passed in most
- recently. For example, if an application uses an AF_SIP form address in
- its bind() call, then a subsequent accept() call would return a
- sockaddr_in structure in the AF_SIP form. If the application calls no
- socket function that passes in an address before calling one that
- returns an address, then that function returns an AF_INET form address.
-
- The socket functions to which an application passes in an address
- argument are:
-
- bind()
- connect()
- sendto()
-
- The socket functions that return an address to the application are:
-
- accept()
- recvfrom()
- getpeername()
- getsockname()
-
-
- 3.4 Sockets passed across exec()
-
- Having two forms of sockaddr_in address that may be used interchageably
- with all AF_INET sockets means that existing applications are supported
- straightforwardly, and that new applications simply need to be written
- to use the AF_SIP form of sockaddr_in. However, Unix allows open
-
-
-
- sockets to be passed across an exec() call. Thus a newly written
- application may find itself holding an open socket that was passed to it
- via exec(), but not knowing what form of addresses that will be
- returned. Similarly, a newly written SIP knowledgeable application may
- wish to use AF_SIP form addresses in its bind() or connect() calls, and
- then pass the socket to a pre-existing application. To remedy these
- problems, we defined a new setsockopt() option that allows an
- application to explicitly set the form of sockaddr_in addresses returned
- by the socket functions. A SIP knowledgeable application that is passed
- an open socket from an unknown process may do use the SIP_ADDRFORM
- setsockopt() option to "convert" the socket to return AF_SIP form
- addresses. Similarly, a SIP knowledgeable application that is about to
- pass an open socket to a program that may not be SIP knowledgeable may
- "downgrade" the socket to return AF_INET form addresses using the same
- setsockopt option.
-
- The macro definition for this new option in <netinet/in.h> is:
-
- #define SIP_ADDRFORM 0x16 /* get/set form of returned addrs */
-
- The SIP_ADDRFORM option is at the IPPROTO_IP level. The only valid
- option values are AF_SIP and AF_INET. For example, to convert a socket
- to return AF_INET form addresses, a program would call:
-
- int addrform = AF_SIP;
-
- if (setsockopt(s, IPPROTO_IP, SIP_ADDRFORM, (char *) &addrform,
- sizeof(addrform)) == -1)
- perror("setsockopt SIP_ADDRFORM");
-
- An application may use SIP_ADDRFORM in the getsockopt() function to
- learn the form of addresses that will be returned by an open socket.
-
-
- 3.5 IPv4 addresses in AF_SIP form sockaddr_in structures
-
- An application may need to pass 32 bit IPv4 address in a sockaddr_in
- structure, but want to set the sin_family field to AF_SIP in order to
- set the form of addresses to be returned. To allow for this, we have
- defined a convention for storing 32 bit IPv4 addresses in 64 bit SIP
- addresses. The 32-bit IPv4 address is stored in the low-order 32 bits
- of the SIP address and the high-order 32 bits (i.e. the prefix part) are
- set to zero. For example, the following structure:
-
- struct sockaddr_in sin1;
-
- sin1.sin_family = AF_SIP;
- sin1.sip_zero = 0;
- *((long *) sin1.sip_addr) = 0;
- *((long *) &sin1.sip_addr[4]) = inet_addr("192.9.9.1");
-
- And this structure:
-
-
-
-
- struct sockaddr_in sin2;
-
- sin2.sin_family = AF_INET;
- sin2.sin_addr.s_addr = inet_addr("192.9.9.1");
- bzero(sin2.sin_zero, sizeof(sin_zero);
-
- are alternative ways to represent the same IPv4 address.
-
- All of the socket functions that accept sockaddr_in addresses passed in
- as arguments accept IPv4 addresses in the AF_SIP form.
-
-
- 3.6 Flow IDs
-
- The SIP header has a 28 bit field reserved to hold a "flow ID". The
- usage of this field has not yet been specified. But in order to allow
- application programmers to experiment with SIP flows, we have defined a
- setsockopt() option that can be used to set the value to be assigned to
- the flow ID field of transmitted SIP packets. So far, we have not
- defined any interface for an application to learn the flow ID set in
- received SIP packets.
-
- The macro definition for this new option in <netinet/in.h> is:
-
- #define SIP_FLOWID 0x15 /* SIP flow identifier */
-
- The SIP_FLOWID option is at the IPPROTO_IP level. An example of how an
- application might use this option is:
-
- int flowid = 0x0f3c91ab; /* random value made up for this example */
-
- if (setsockopt(s, IPPROTO_IP, SIP_FLOWID, (char *) &flowid,
- sizeof(flowid)) == -1)
- perror("setsockopt SIP_ADDRFORM");
-
- The SIP_FLOWID option can also be used with the getsockopt() option to
- retrieve the flow ID value given in the last setsockopt() call.
-
- Since the definition of SIP flows may change as the protocol develops,
- this option may also change in the future. Thus application developers
- should consider this option "experimental."
-
-
- 3.7 Name-to-address translation functions
-
- We have defined a new function call with the form:
-
- struct hostent *hostname2addr(const char *name, int af,
- char *buf, int buflen);
-
- This interface looks the given host name up in the naming service and
- returns a list of addresses. The name argument is the name of the host
- to look up. The af argument specifies what form of address -- 4-byte
-
-
-
- IPv4 or 8-byte SIP address -- to return to the caller in the h_addr_list
- field of the hostent structure. The buf argument points to a buffer
- that the function can use to store the hostent structure that is
- returned. The buflen argument is the size of the buffer. If buf is a
- null pointer, the function uses its own static buffer.
-
- If the af argument is AF_INET, hostname2addr() behaves like
- gethostbyname(). That is, it returns a hostent structure which includes
- an array of 4-byte IPv4 addresses. If AA (SIP address) records are
- found, then the low-order 4 bytes of each SIP address are returned. If
- only A records are found, then the associated 4-byte IP address is
- returned.
-
- If the type argument is AF_SIP, then the h_addr_list field of the
- hostent structure contains an array of 8-byte SIP addresses. If AA
- records are found, then the full SIP address of each record is returned.
- If only A records are found, then each 8-byte address returned holds the
- IPv4 address in the low-order 4 bytes and the high-order 4 bytes are set
- to zero. (i.e. it uses the convention for storing IPv4 addresses in SIP
- addresses defined above).
-
- There was some discussion on the SIP mailing list of some other ways to
- cast this function. This proposal allows the application to be simple.
- Since it passes in the address family, the application knows the size of
- the returned addresses and can unconditionally bcopy() them into
- sockaddr_in structures. Also, the semantics of the hostname2addr() when
- af is AF_INET lets us implement the existing gethostbyname() function in
- terms of the new function.
-
- The gethostbyaddr() function remains unchanged:
-
- struct hostent *gethostbyaddr(const char *addr, int len, int af);
-
- If the af argument is AF_INET, then len must be 4 and addr points to a
- 4-byte IPv4 address. If af is AF_SIP, then len must be 8 and addr
- points to an 8-byte SIP address.
-
-
- 3.8 Address input/output functions
-
- BSD Unix provides two functions -- inet_addr() and inet_ntoa() -- to
- convert IPv4 address between binary and printable form. SIP
- applications need similar functions. We have defined the following two
- functions to convert SIP and IPv4 addresses:
-
- int ascii2addr(long af, char *cp, char *ap);
-
- and
-
- char *addr2ascii(long af, char *ap, char *buf, int buflen)
-
-
- The first function is used to transform an ascii string into an address
- data structure. The af argument specifies that address family of the
-
-
-
- address. Currently AF_INET and AF_SIP are supported. The cp argument
- points to the ascii string being passed in. The ap argument points to
- the 4-byte or 8-byte buffer that the address will be converted into.
-
- If the af argument is AF_INET, the function accepts a string in the
- standard IPv4 dotted decimal form:
-
- ddd.ddd.ddd.ddd
-
- Where ddd is a one to three digit decimal number between 0 and 255.
-
- If the af argument is AF_SIP, then the function accepts a string in the
- standard IPv4 dotted decimal form given above, or a string in one of the
- two standard SIP printing forms:
-
- xxxx:xxxx:ddd.ddd.ddd.ddd
- or
- xxxx:xxxx:xxxx:xxxx
-
- where xxxx is a 1 to 4 digit hex value and ddd is a 1 to 3 digit decimal
- number between 0 and 255. If the string is in the IPv4 dotted decimal
- form, the high order 4 bytes of the address buffer pointed to by ap are
- set to zero and the low-order 4 bytes are set to the IPv4 address.
-
- Having the AF_SIP variant of the ascii2addr() function accept either
- IPv4 addresses or SIP addresses allows an application to easily accept
- either form of address from the user.
-
- The second function transforms an address buffer into a printable
- string. The af argument specifies the form of the address. This can be
- AF_INET or AF_SIP. The ap argument points to a buffer holding a 4-byte
- IPv4 address or an 8-byte SIP address. The buf argument points to a
- buffer that the function can convert into, and the buflen argument gives
- the size of this buffer. If the buf argument is zero, then the function
- will convert the address unto a private static buffer of its own. In
- either case, the function returns a pointer to the buffer that the
- address has been converted into.
-
- The ascii2addr() function returns 0 if the conversion succeeded, and -1
- if it failed. The function does not modify the storage pointed to by ap
- if the conversion fails. The addr2ascii() function returns a pointer to
- the buffer if the conversion succeeded, and -1 if the conversion failed.
-
- These two functions are derived from suggestions by Craig Partridge on
- the SIP mailing list. There was some discussion about whether the
- buffer that addr2ascii() converts into should be static within the
- function() or passed in by the application. In the interface presented
- here, we try to provide the best of both worlds.
-
- 4. Open Issues
-
- The API changes described here are likely to change as we get experience
- writing SIP applications. There are also some issues left unresolved.
- Some of the things we need to think about are:
-
-
-
-
- - There is a type defined (in_addr) to represent a 32-bit IPv4
- address. Should we define a structure to hold the 64-bit SIP
- address? There was some discussion of this on the SIP mailing
- list with opinions on both sides.
-
- - The format of the "/etc/hosts" file currently supports only IPv4
- addresses. Should we extend the format of the existing file to
- handle SIP addresses? Or should we invent a file with a new
- name for storing SIP host addresses? Andrew Cherenson suggests
- a clever, but ugly, hack to re-use the same file and allow old
- and new versions of gethosb* to co-exist: precede SIP lines with
- "#SIP", which acts as comment for old versions.
-
- - How do datagram applications participate in path MTU discovery?
-
- - What about the SIOC* ioctl() commands that get and set interface
- parameters and manipulate the IP routing table?
-
- - Posix is changing and standardizing the socket interface.
- Should we track the posix changes? In particular, 4.3-Reno has
- split the 16-bit address family field of the sockaddr struct
- into two 8-bit fields: a length field and an address family
- field. Should we adopt this here?
-
- - This spec has concentrated on the BSD socket interface. What
- about the System V Transport Library Interface (TLI)? Does
- anyone really care about TLI?
-
- - The BSD "net-2" release includes setsockopt options to set the
- IP TTL. Should we specify that this option sets the SIP hop
- limit, or is this just obvious?
-
-
- 5. Security Considerations
-
- Security issues are not discussed in this document.
-
-
- 6. Acknowledgements
-
- Thanks to all who provided feedback to the first revision of this
- document, including Christian Huitema, Craig Partridge, Steve Deering,
- Andrew Cherenson, Charles Lynn, Ran Atkinson, Erik Nordmark, Glenn
- Trewitt, Fred Baker, Robert Elz, and Dean D. Throop.
-
-
- 7. References
-
- [1] Deering, S., "Simple Internet Protocol (SIP) Specification",
- Internet Draft November 1992
-
-
-
- 8. Authors' Address
-
- Robert E. Gilligan
- Sun Microsystems, Inc.
- 2550 Garcia Avenue
- Mailstop UMTV05-44
- Mountain View, California 94043-1100
-
- 415-336-1012
-
- bob.gilligan@eng.sun.com
-
-